/*
xp_time.c
offer system time data,acture time
designed by lunanting

---------------------------
2020-05-10 16:57:07
create file
---------------------------
*/
#include "xp_time.h"
#include "time.h"
#include "aos/kernel.h"
#include "stdio.h"
#include "../driver/rtc/rtc_time.h"
#include "cli_cmd.h"

static u64 basetimeMS=0,basesystickMS=0;
static char dateString[50]={0};


static int xp_rtc_debug(char *type,char *fun,char *param);


/*
set base time
param:
    time:unix time
*/
void xp_time_set_unix(u64 time){
    basetimeMS=time*1000;
    basesystickMS=aos_now_ms();
}

/*
set base time ms
param:
    timems:time ms
*/
void xp_time_set_ms(u64 timems){
    basetimeMS=timems;
    basesystickMS=aos_now_ms();
}


/*
get unix time
return:unix time
*/
u64 xp_time_get_unix(void){
    u64 timenow=aos_now_ms();
    return (basetimeMS+timenow-basesystickMS)/1000;
}

/*
get ms time
return:ms time
*/
u64 xp_time_get_ms(void){
    u64 timenow=aos_now_ms();
    return basetimeMS+timenow-basesystickMS;
}


/*
get DATE string
return:date string
*/
char *xp_time_get_string(void){
#if 1
    struct tm *p;
    u64 timenow=aos_now_ms();
    time_t unixtime=(basetimeMS+timenow-basesystickMS)/1000;
    p=localtime(&unixtime);
    sprintf(dateString,"%04d-%02d-%02d %02d:%02d:%02d",p->tm_year+1900,
                                                    p->tm_mon+1,
                                                    p->tm_mday,
                                                    p->tm_hour,
                                                    p->tm_min,
                                                    p->tm_sec);
    return dateString;
#else
    strncpy(dateString, xp_rtc_get_string(), sizeof(dateString));
    return dateString;
#endif
}


/*
get date string
return: date string format xxxx-xx-xx
*/
char *xp_date_string_get(void){
    static char date[30]={0};
    struct tm *t;
    u64 sec=xp_time_get_unix();

    t=localtime((time_t *)&sec);
    sprintf(date,"%04d-%02d-%02d",t->tm_year+1900,
                                t->tm_mon+1,
                                t->tm_mday);
    return date;
}

/*
get date-hour string
return: date-hour format string, format: xxxx-xx-xx-xx
*/
char *xp_date_hour_string_get(void){
    static char date_hour[30]={0};
    struct tm *t;
    u64 sec=xp_time_get_unix();

    t=localtime((time_t *)&sec);
    sprintf(date_hour,"%04d-%02d-%02d-%02d",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour);
    return date_hour;
}


/*
get time string with miro sec
return: time string ms
*/
char *xp_timeMS_string_get(void){
    static char ms[30]={0};
    struct tm *p;
    u64 t_ms=xp_time_get_ms();
    u64 t_sec=t_ms/1000;

    p=localtime((time_t *)&t_sec);
    sprintf(ms,"%04d-%02d-%02d %02d:%02d:%02d.%03d",p->tm_year+1900,
                                                    p->tm_mon+1,
                                                    p->tm_mday,
                                                    p->tm_hour,
                                                    p->tm_min,
                                                    p->tm_sec,
                                                    t_ms%1000);

    return ms;
}

/*
get diff ms from start_time
return: diff time
*/
u64 xp_time_get_diff_ms(u64 start_time){
    u64 diff_ms = 0;
    u64 cur_time = aos_now_ms();

    if(cur_time > start_time){
        diff_ms = cur_time - start_time;
    }else{
        //处理翻转的情况
        diff_ms = 0xFFFFFFFFFFFFFFFFULL - start_time + cur_time;
    }

    return diff_ms;
}


/*
change micro secends to daysn format string
format: dddd-hh-mm-ss-ms
param:
    ms= input ms
return:
    format string
*/
char* xp_msTostring(u64 ms){
    static char days[30]={0};
    int date[5];
    int div=0;

    div=1000*60*60*24;
    date[0]=ms/div;
    ms=ms%div;
    div=1000*60*60;
    date[1]=ms/div;
    ms=ms%div;
    div=1000*60;
    date[2]=ms/div;
    ms=ms%div;
    div=1000;
    date[3]=ms/div;
    ms=ms%div;
    date[4]=ms;
    if(date[0]!=0){
        sprintf(days,"%ddays-%dhours-%dmin-%ds.%03dms",date[0],date[1],date[2],date[3],date[4]);
    }
    else if(date[1]!=0){
        sprintf(days,"%dhours-%dmin-%ds.%03dms",date[1],date[2],date[3],date[4]);
    }
    else if(date[2]!=0){
        sprintf(days,"%dmin.%ds.%03dms",date[2],date[3],date[4]);
    }
    else if(date[3]!=0){
        sprintf(days,"%ds.%03dms",date[3],date[4]);
    }
    else{
        sprintf(days,"%03dms",date[4]);
    }
    return days;
}


#include "aos/hal/rtc.h"


/*
init external rtc 
*/
int xp_rtc_init(void){
    int sta=0;

    xp_cli_debug_add(xp_rtc_debug);
    sta=hal_rtc_init(NULL);
    xp_rtc_get();
    
    return sta;
} 


/*
set external rtc time
param:
    time: hal time structer
return:
    0=success
*/
int xp_rtc_set(RTC_time *time){
    rtc_dev_t  rtc={0};

    rtc.port=1;
    rtc.config.format=HAL_RTC_FORMAT_DEC;

    return hal_rtc_set_time(&rtc,time);
}



/*
get external rtc time
return: RTC_time pointer
*/
RTC_time *xp_rtc_get(void){
    rtc_dev_t  rtc={0};
    static rtc_time_t time={0};
    struct tm t={0};
    time_t sec=0;

    rtc.port=1;
    rtc.config.format=HAL_RTC_FORMAT_DEC;

    hal_rtc_get_time(&rtc,&time);
    t.tm_year=time.year-1900;
    t.tm_mon=time.month-1;
    t.tm_mday=time.date;
    t.tm_hour=time.hr;
    t.tm_min=time.min;
    t.tm_sec=time.sec;
    t.tm_isdst=-1;
    sec=mktime(&t);
    xp_time_set_unix((u64)sec);
    return (RTC_time *)&time;
}


/*
set external rtc with unix time sec
param:
    unix: unix sec s
return:
    0=success
*/
int xp_rtc_set_with_unix(int unix){
    struct tm *tp;
    RTC_time time_s={0};

    unix += 8*3600;             //东八区
    tp=localtime(&unix);
    xp_time_set_unix(unix);
    time_s.year=tp->tm_year+1900;
    time_s.month=tp->tm_mon+1;
    time_s.date=tp->tm_mday;
    time_s.weekday=tp->tm_wday+1;
    time_s.hr=tp->tm_hour;
    time_s.min=tp->tm_min;
    time_s.sec=tp->tm_sec;

    xp_rtc_set(&time_s);
    println("set time: %04d-%02d-%02d %02d:%02d:%02d.",tp->tm_year+1900,
                                                                tp->tm_mon+1,
                                                                tp->tm_mday,
                                                                tp->tm_hour,
                                                                tp->tm_min,
                                                                tp->tm_sec);
    return 0;
}




/*******************************debug ********************************/
static int xp_rtc_debug(char *type,char *fun,char *param){
    if(strstr(type,"rtc")==NULL)return 0;

    if(strstr(fun,"set")!=NULL){
        xp_rtc_set_with_unix(atoi(param));
    }
    else if(strstr(fun,"systick")!=NULL){
        println("systick: %lld.",aos_now_ms());
    }
    else{
        return 0;
    }
    return 1;
}


//end of the file
